其他
从0开始实现一个简易的主动调用框架
本文为看雪论坛优秀文章
看雪论坛作者ID:r0ysue
总述
加载方案
https://bbs.pediy.com/thread-252630.htm
private void handleBindApplication(AppBindData data) {
//step 1: 创建LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
//step 2: 创建ContextImpl对象;
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
//step 3: 创建Instrumentation
mInstrumentation = new Instrumentation();
//step 4: 创建Application对象;在makeApplication函数中调用了newApplication,在该函数中又调用了app.attach(context),在attach函数中调用了Application.attachBaseContext函数
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//step 5: 安装providers
List<ProviderInfo> providers = data.providers;
installContentProviders(app, providers);
//step 6: 执行Application.Create回调
mInstrumentation.callApplicationOnCreate(app);
}
public static void mycopy(String srcFileName, String trcFileName) {
InputStream in = null;
OutputStream out = null;
try {
// in = File.open(srcFileName);
in = new FileInputStream(srcFileName);
out = new FileOutputStream(trcFileName);
byte[] bytes = new byte[1024];
int i;
while ((i = in.read(bytes)) != -1)
out.write(bytes, 0, i);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null)
in.close();
if (out != null){
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleBindApplication(AppBindData data) {
......
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
ContextImpl context = appContext;
ActivityManager mAm = (ActivityManager) context.getSystemService("activity");
String activity_packageName = mAm.getRunningTasks(1).get(0).topActivity.getPackageName();//获得私有目录
if (activity_packageName.indexOf("com.android") < 0) {//不包括系统目录
String tagPath = "/data/data/" + activity_packageName + "/r0.so";//64位so的目录
String tagPath2 = "/data/data/" + activity_packageName + "/r032.so";//32位的so目录
File file1 = new File(tagPath);
File file2 = new File(tagPath2);
mycopy("/sdcard/r0.so", tagPath);//复制so到私有目录
mycopy("/sdcard/r032.so", tagPath2);
int perm = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO;
FileUtils.setPermissions(tagPath, perm, -1, -1);//将权限改为777
FileUtils.setPermissions(tagPath2, perm, -1, -1);
// com.android.systemui
if (file1.exists()) {
Log.e("r0ysue", System.getProperty("os.arch"));//判断是64位还是32位
if (System.getProperty("os.arch").indexOf("64") >= 0) {
System.load(tagPath);
file1.delete();//用完就删否则不会更新
} else {
System.load(tagPath2);
file2.delete();
}
}
}
......
}
java函数调用方案
const char * getprocessname(JNIEnv* env){
jclass ActivityThread=env->FindClass("android/app/ActivityThread");
jmethodID currentProcessName=env->GetStaticMethodID(ActivityThread,"currentProcessName","()Ljava/lang/String;");
jstring name= static_cast<jstring>(env->CallStaticObjectMethod(ActivityThread,currentProcessName));
const char * name1=env->GetStringUTFChars(name,0);
return name1;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) {
JNIEnv* env= nullptr;
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4);
const char* myname= getprocessname(env);
__android_log_print(6,"r0ysue","i am from %s",myname);
return JNI_VERSION_1_4;
}
unzip app-debug.apk
cd lib/arm64-v8a/
adb push libnative-lib.so /sdcard/r0.so
调用Native函数
https://bbs.pediy.com/thread-269757.htm
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) {
mainfun("_ZN3art9ArtMethod14RegisterNativeEPKvb", "libart.so",
reinterpret_cast<void *>(regist));
return JNI_VERSION_1_4;
}
void regist(void* a,void* b,int c){
const char* ds=getartmethod((unsigned int *)a);
if(strstr(ds,"xxxxxx")){//过滤函数名
st=b;
long* d= reinterpret_cast<long *>(myreplace);//替换的注册函数
__android_log_print(6,"r0ysue","%p",d);
__asm__("str %[input_n], [X18,#0x28]\r\n"//修改registernative的第二个参数,我这里用x18传的调用栈
:[result_m] "=r" (d)
:[input_n] "r" (d)
);
__android_log_print(6,"r0ysue","register %s",ds);
}
}
void* myreplace(void* a,void* b,int c,void* d){
JNIEnv* env= static_cast<JNIEnv *>(a);
jobject aa= static_cast<jobject>((docomm(st))(a, b, reinterpret_cast<void *>(c), d));//直接调用原函数
if(aa!= nullptr) {//由于返回值是一个jstring判断一下
env->SetObjectArrayElement(static_cast<jobjectArray>(d), 2, env->NewStringUTF("4"));
jobject opp= static_cast<jobject>((docomm(st))(a, b, reinterpret_cast<void *>(c), d));//调用将第2个字符串改为4之后的字符串
__android_log_print(6,"r0ysue"," 111111111111 %s",env->GetStringUTFChars(
static_cast<jstring>(opp),0));//这个jobject数组是一个长度为5的字符串数组,就是说有5个字符串我随便改一个就好
const char *ss = getclassname(env,myclass);
if(strstr(ss,"String")) {//由于返回值是一个jstring判断一下再打印
printobjearry(env,(jobjectArray)d);//打印jobject数组
__android_log_print(6, "r0ysue", " ssssssss int:%x %s", c,env->GetStringUTFChars(
static_cast<jstring>(aa), 0));
}
}
return aa;
}
void printobjearry (JNIEnv* env,jobjectArray a){//打印jobjet数组
int size=env->GetArrayLength(static_cast<jarray>(a));
for(int n=0;n<size;n++) {
jobject ax=env->GetObjectArrayElement(static_cast<jobjectArray>(a), n);
if(ax!=0)
__android_log_print(6, "r0ysue", " ssssssss %d: %s",n, getclassname(env, ax));
}
}
const char * getartmethod(unsigned int *a1){//ArtMethod中的getName函数直接从ida复制过来的
__int64 v12; // x20
__int64 v13; // x0
_QWORD *v14; // x8
__int64 v15; // x9
char *v16; // x8
const char *result; // x0
unsigned int **v18; // x8
unsigned int *v19; // x9
unsigned int *v20; // x9
int v21; // w10
const char *v22; // x9
const char *v23; // x8
unsigned int **v24; // x20
__int64 v25; // x0
__int64 v26; // x0
unsigned int **v27; // x20
__int64 v28; // x0
__int64 v29; // x0
unsigned int *v30; // [xsp+48h] [xbp+18h]
unsigned int *v31; // [xsp+48h] [xbp+18h]
v12 = a1[3];
if ( (a1[1] & 0x40000) != 0 ) {
// _ZN3art9ArtMethod19GetObsoleteDexCacheEv
return "cxzcxzcxz";
}
else
v13 = *(unsigned int *)(*a1 + 0x10LL);
v14 = *(_QWORD **)(v13 + 16);
v15 = *(unsigned int *)(v14[12] + 8 * v12 + 4);
if ( (_DWORD)v15 == -1 )
return 0LL;
v16 = (char *)(v14[1] + *(unsigned int *)(v14[9] + 4 * v15));
result = v16 + 1;
if ( (*v16 & 0x80000000) != 0 )
{
if ( (v16[1] & 0x80000000) != 0 )
{
if ( (v16[2] & 0x80000000) != 0 )
{
v21 = v16[3];
v22 = v16 + 4;
v23 = v16 + 5;
if ( v21 >= 0 )
result = v22;
else
result = v23;
}
else
{
result = v16 + 3;
}
}
else
{
result = v16 + 2;
}
}
return result;
}
总结
参考资料
https://bbs.pediy.com/thread-266767.htm
https://bbs.pediy.com/thread-252630.htm
看雪ID:r0ysue
https://bbs.pediy.com/user-home-799845.htm
# 往期推荐
2.Android APP漏洞之战——权限安全和安全配置漏洞详解
4.Android APP漏洞之战——Activity漏洞挖掘详解
球分享
球点赞
球在看
点击“阅读原文”,了解更多!